package com.denlaku.longan.service.impl;

import com.denlaku.longan.BizModule;
import com.denlaku.longan.core.Current;
import com.denlaku.longan.core.Terminal;
import com.denlaku.longan.service.DashboardIndexService;
import com.denlaku.longan.index.IndexHolder;
import com.denlaku.longan.index.IndexQuery;
import com.denlaku.longan.service.IndexService;
import com.denlaku.longan.util.Lists;
import com.denlaku.longan.util.Objects;
import com.denlaku.longan.vo.Dashboard;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.List;
import java.util.Map;

/**
 * @author tianx
 */
@Service
public class DashboardIndexServiceImpl implements DashboardIndexService {
    @Autowired
    private IndexService indexService;

    @Override
    public List<Map<String, String>> search(String keyword, Terminal terminalType) {
        IndexQuery indexQuery = buildIndexQuery(terminalType);
        indexQuery.setFields(Lists.of("title"));
        indexQuery.setKeyword(keyword);
        List<Document> documents = indexService.search(indexQuery);
        List<Map<String, String>> result = Lists.ofSize(documents.size());
        for (Document document : documents) {
            List<IndexableField> fields = document.getFields();
            Map<String, String> map = Lists.toMap(fields, IndexableField::name, IndexableField::stringValue);
            result.add(map);
        }
        return result;
    }

    @Override
    public void buildIndex(Dashboard dashboard) {
        IndexHolder holder = new IndexHolder();
        holder.setTenantId(dashboard.getTenantId());
        holder.setBiz(BizModule.DASHBOARD + File.separator + dashboard.getTerminal().name());
        Document document = buildDocument(dashboard);
        holder.addDocument(document);
        this.deleteIndex(dashboard);
        indexService.index(holder);
    }

    private void deleteIndex(Dashboard dashboard) {
        IndexQuery indexQuery = buildIndexQuery(dashboard.getTerminal());
        indexQuery.setFields(Lists.of("id"));
        indexQuery.setKeyword(String.valueOf(dashboard.getId()));
        indexService.delete(indexQuery);
    }

    private IndexQuery buildIndexQuery(Terminal terminalType) {
        IndexQuery indexQuery = new IndexQuery();
        indexQuery.setTenantId(Current.getTenantId());
        indexQuery.setBiz(BizModule.DASHBOARD + File.separator + terminalType.name());
        return indexQuery;
    }

    private Document buildDocument(Dashboard dashboard) {
        Document document = new Document();
        FieldType idType = new FieldType();
        idType.setTokenized(false);
        idType.setStored(true);
        idType.setIndexOptions(IndexOptions.DOCS);
        Field idField = new Field("id", String.valueOf(dashboard.getId()), idType);
        document.add(idField);

        FieldType nameType = new FieldType();
        nameType.setTokenized(true);
        nameType.setStored(true);
        nameType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
        Field nameField = new Field("title", dashboard.getTitle(), nameType);
        document.add(nameField);

        FieldType terminalType = new FieldType();
        terminalType.setTokenized(false);
        terminalType.setStored(true);
        Field terminalField = new Field("terminal", dashboard.getTerminal().getCode(), terminalType);
        document.add(terminalField);

        FieldType bizType = new FieldType();
        bizType.setTokenized(false);
        bizType.setStored(true);
        Field bizField = new Field("biz", "dashboard", bizType);
        document.add(bizField);

        Objects.ifPresent(dashboard.getDesc(), desc -> {
            FieldType descType = new FieldType();
            descType.setTokenized(true);
            descType.setStored(true);
            descType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
            Field descField = new Field("desc", desc, descType);
            document.add(descField);
        });

        return document;
    }
}
